home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-04-10 | 60.5 KB | 1,509 lines |
- program ImageUtility;
- { 4/9/98 }
-
- {$path "PasI:"}
- {$incl "libraries/dos.h" }
- {$incl "DOS/DateTime.h" }
-
- const addrK = #$96;
- dataK = #$AD;
- secImSize = 143360;
-
- type arg = string[64];
- imageDef = (none, notIm, bitIm, secIm);
- orderDef = (oDO, oPO);
- DOSdef = (DOS33, Pascal, ProDOS, dual1, dual2, unknown);
- modeDef = (cat, insert, extract, delete, reord, cvt);
- profileDef = record
- count,
- t: byte;
- data: array[0..7] of record
- s,
- offs,
- v: byte
- end
- end;
- pathN = string[107];
- sector = array[0..255] of byte;
- track = array[0..15] of sector;
-
- var firstTime, parmsOK, hit, xlate, indent, writeIt,
- getSize, scanSize, changeSize, scanData, match, done: Boolean;
- volHi, volLo, trkNo, prevT, secNo, TSLt, TSLs, s, AReg, entTyp, byt: byte;
- access, hi, lo, ordCh, ch: char;
- answer, fileSz, newSize, offset, start, firstThree: long;
- argC,
- front, back, count,
- entCount, entSz, mapBlock, totBlocks, blkNo, offs,
- entries, blocks, free, used, largest, unused,
- file_type, stop, size,
- lastTrk, countA, countD,
- i, j, k, m, n: integer;
- ifTyp: imageDef;
- order: orderDef;
- mode: modeDef;
- format: DOSdef;
- option, suffix: string[3];
- fileTyp, kind: string[4];
- volN: string[15];
- mDate, cDate, mTime, cTime: dat_String;
- afName, dirName: string[32];
- currArg, newArg: arg;
- f: BPTR;
- aif: file of byte;
- aof: file;
- dtWork: DateTime;
- ifName, afPath, ofName: pathN;
- args: array[1..16] of arg;
- months: array[0..12] of string[3];
- XORTable: array[$96..$FF] of byte;
- D33_DO, D33_PO, PDOS_DO, PDOS_PO, Pascal_DO, Pascal_PO: profileDef;
- fTypes: array[1..13] of record
- value: byte;
- desc: string[3]
- end;
- rawData: array[0..342] of byte
- LowBits: array[0..85] of byte;
- workSector: sector;
- rearrTrack: track;
- dirEnt: array[0..39] of byte;
- sectors: array[0..34] of track;
- blkAddrs: array[0..255] of word;
- image: array[0..249999] of byte;
-
- function secD33(s: byte): byte;
- begin
- if (s = 0) or (s = 15)
- then secD33 := s
- else secD33 := 15 - s
- end;
-
- function is(p: profileDef): Boolean;
- var b: Boolean;
- limit, trk, i: integer;
- begin
- b := true;
- trk := p.t;
- for i := 0 to p.count - 1
- do if sectors[trk][p.data[i].s][p.data[i].offs] <> p.data[i].v
- then b := false;
- is := b
- end;
-
- function classify(n: pathN): imageDef;
- var fileSize: long;
- lockPtr: BPTR;
- FileIB: p_FileInfoBlock;
- begin
- lockPtr := Lock(n, ACCESS_READ);
- if lockPtr = 0
- then classify := none
- else begin
- new(FileIB);
- answer := Examine(lockPtr, FileIB);
- fileSize := FileIB^.fib_size;
- Unlock(lockPtr);
- dispose(FileIB);
- if fileSize = secImSize
- then begin
- { determine if 'DO' or 'PO' }
- classify := secIm { default, for now }
- end
- else begin
- if fileSize < secImSize
- then classify := notIm
- else begin
- { validate part of file? }
- classify := bitIm
- end
- end
- end
- end;
-
- function un4x4(xx, yy: byte): byte;
- begin
- un4x4 := ((xx and $55) shl 1) + (yy and $55)
- end;
-
- function get_dir_byte(o: integer): byte;
- begin
- get_dir_byte := sectors[0][4 + o div 256][o mod 256]
- end;
-
- function get_dir_word(o: integer): integer;
- begin
- get_dir_word := get_dir_byte(o + 1) * 256 + get_dir_byte(o)
- end;
-
- procedure formatDate(high, low: byte; var d: dat_String);
- var year, month, day: integer;
- temp: dat_String;
- begin
- if high + low = 0
- then temp := '<NO DATE>'
- else begin
- year := high div 2;
- if format = Pascal
- then begin
- month := low mod 16;
- day := low div 16;
- if odd(high)
- then day := day + 16;
- end
- else begin
- month := low shr 5;
- if odd(high)
- then month := month + 8;
- day := low and $1F
- end;
- if (month < 1) or (month > 12)
- then month := 0;
- temp := chr(day div 10 + 48) + chr(day mod 10 + 48)
- + '-' + months[month] + '-'
- + chr(year div 10 + 48) + chr(year mod 10 + 48);
- if temp[1] = '0'
- then temp[1] := ' '
- end;
- d := temp
- end;
-
- procedure formatTime(high, low: byte; var d: dat_String);
- var hour, min: integer;
- temp: dat_String;
- begin
- temp := chr(high div 10 + 48) + chr(high mod 10 + 48)
- + ':'
- + chr(low div 10 + 48) + chr(low mod 10 + 48);
- if temp[1] = '0'
- then temp[1] := ' ';
- d := temp
- end;
-
- procedure show_free(f: integer);
- begin
- if f > largest
- then largest := f;
- unused := unused + f;
- writeln('< UNUSED > ', f:4, ' ', stop:4)
- end;
-
- procedure toHex(v: byte; var a, b: char);
- function hexNyb(n: byte): char;
- begin
- if n < 10
- then hexNyb := chr(n + 48)
- else hexNyb := chr(n + 55)
- end;
- begin
- a := hexNyb(v shr 4);
- b := hexNyb(v and $0F)
- end;
-
- procedure catalog;
- begin
- case format of
- DOS33: begin
- trkNo := 17;
- secNo := 15;
- writeln('Volume number: ', sectors[17][0][6]);
- writeln('Diskette initialized by version ', sectors[17][0][3]);
- writeln(sectors[17][0][52], ' tracks');
- writeln(sectors[17][0][53], ' sectors');
- writeln(sectors[17][0][55] * 256 + sectors[17][0][54],
- ' bytes per sector');
- repeat
- for i := 0 to 6
- do begin
- for j := 0 to 34
- do dirEnt[j] := sectors[trkNo][secNo][i * 35 + j + 11];
- if (dirEnt[0] > 0) and (dirEnt[0] <> 255)
- then begin
- dirName := '';
- for j := 0 to 29
- do dirName := dirName + chr(dirEnt[3 + j] and $7F);
- fileSz := dirEnt[34] * 256 + dirEnt[33];
- case dirEnt[2] and $7F of
- 0: fileTyp := 'TEXT';
- 1: fileTyp := 'IBAS';
- 2: fileTyp := 'ABAS';
- 4: fileTyp := 'BIN ';
- 8: fileTyp := 'TypS';
- 16: fileTyp := 'RELO';
- 32: fileTyp := 'TypA';
- 64: fileTyp := 'TypB'
- else fileTyp := 'Unk '
- end;
- writeln(dirName, fileSz:6, ' ', fileTyp)
- end
- end;
- prevT := trkNo;
- trkNo := sectors[prevT][secNo][1];
- secNo := secD33(sectors[prevT][secNo][2])
- until trkNo = 0;
- writeln
- end;
- Pascal: begin
- volN := '';
- for i := 1 to get_dir_byte(6)
- do volN := volN + chr(get_dir_byte(6 + i));
- formatDate(sectors[0][4][21], sectors[0][4][20], cDate);
- writeln(volN, ': ', cDate);
- blocks := get_dir_word(14);
- entries := get_dir_byte(16);
- unused := 0;
- largest := 0;
- stop := 6;
- for i := 1 to entries
- do begin
- offset := i * 26;
- start := get_dir_word(offset);
- if (start <> stop)
- then show_free(start - stop);
- stop := get_dir_word(offset + 2);
- file_type := get_dir_word(offset + 4);
- size := get_dir_byte(offset + 6);
- dirName := '';
- for j := 1 to size
- do dirName := dirName + chr(get_dir_byte(offset + 6 + j));
- if size < 15
- then for j := 15 downto size + 1
- do dirName := dirName + ' ';
- formatDate(get_dir_byte(offset + 25),
- get_dir_byte(offset + 24),
- cDate);
- write(dirName, ' ', stop - start:4, ' ', cDate, start:5, ' ');
- case file_type of
- 1: kind := 'Bad ';
- 2: kind := 'Code';
- 3: kind := 'Text';
- 4: kind := 'Typ4';
- 5: kind := 'Data';
- 7: kind := 'Typ7'
- else kind := '????'
- end;
- writeln(kind)
- end;
- if stop <> blocks
- then show_free(blocks - stop);
- writeln(entries, '/', entries, ' files, ',
- unused, ' unused, ',
- largest, ' in largest');
- writeln
- end;
- ProDOS: begin
- volN := '/';
- for i := 1 to sectors[0][4][4] and $0F
- do volN := volN + chr(sectors[0][4][4 + i]);
- writeln(volN);
- writeln;
- writeln(' NAME TYPE BLOCKS ',
- 'MODIFIED CREATED ENDFILE SUBT.');
- writeln;
- entCount := sectors[0][4][36];
- entSz := sectors[0][4][35];
- blkNo := 2;
- repeat
- trkNo := blkNo div 8;
- secNo := (blkNo * 2) mod 16;
- for i := 0 {+ firstTime }to entCount - 1
- do begin
- for j := 0 to entSz - 1
- do begin
- offs := i * entSz + j + 4;
- dirEnt[j] := sectors[trkNo][secNo + offs div 256][offs mod 256]
- end;
- entTyp := dirEnt[0] shr 4;
- if ((entTyp >= 1) and (entTyp <= 3)) or (entTyp = 13)
- then begin
- if dirEnt[30] and $02 = 0
- then access := '*'
- else access := ' ';
- dirName := '';
- size := dirEnt[0] and $0F;
- for j := 1 to size
- do dirName := dirName + chr(dirEnt[j]);
- for j := size + 1 to 16
- do dirName := dirName + ' ';
- j := 0;
- repeat
- J := j + 1;
- match := dirEnt[16] = fTypes[j].value
- until match or (j = 13);
- if match
- then fileTyp := fTypes[j].desc
- else begin
- toHex(dirEnt[16], hi, lo);
- fileTyp := '$' + hi + lo
- end;
- formatDate(dirEnt[34], dirEnt[33], mDate);
- if mDate = '<NO DATE>'
- then mTime := ' '
- else formatTime(dirEnt[36], dirEnt[35], mTime);
- formatDate(dirEnt[25], dirEnt[24], cDate);
- if cDate = '<NO DATE>'
- then cTime := ' '
- else formatTime(dirEnt[27], dirEnt[26], cTime);
- writeln(access, dirName, fileTyp,
- dirEnt[20] * 256 + dirEnt[19]:8,
- ' ', mDate, ' ', mTime,
- ' ', cDate, ' ', cTime,
- dirEnt[23] * 65536 + dirEnt[22] * 256 + dirEnt[21]:9)
- end
- end;
- blkNo := sectors[trkNo][secNo][3] * 256 + sectors[trkNo][secNo][2]
- until blkNo = 0;
- writeln;
- totBlocks := sectors[0][4][42] * 256 + sectors[0][4][41];
- mapBlock := (sectors[0][4][40] * 256 + sectors[0][4][39]) * 2;
- free := 0;
- used := 0;
- for i := 0 to totBlocks - 1
- do begin
- if sectors[0][mapBlock][i div 8] and (1 shl (i mod 8)) = 0
- then used := used + 1
- else free := free + 1
- end;
- writeln('BLOCKS FREE:', free:5,
- ' BLOCKS USED:', used:5,
- ' TOTAL BLOCKS:', totBlocks:5);
- writeln
- end;
- unknown: writeln('Unknown operating system!')
- end
- end;
-
- begin
- {$r-}
- for i := $98 to $FF
- do XORTable[i] := 0;
- XORTable[$96] := 0;
- XORTable[$97] := 1;
- XORTable[$9A] := 2;
- XORTable[$9B] := 3;
- XORTable[$9D] := 4;
- XORTable[$9E] := 5;
- XORTable[$9F] := 6;
- XORTable[$A6] := 7;
- XORTable[$A7] := 8;
- XORTable[$AB] := 9;
- XORTable[$AC] := 10;
- XORTable[$AD] := 11;
- XORTable[$AE] := 12;
- XORTable[$AF] := 13;
- XORTable[$B2] := 14;
- XORTable[$B3] := 15;
- XORTable[$B4] := 16;
- XORTable[$B5] := 17;
- XORTable[$B6] := 18;
- XORTable[$B7] := 19;
- XORTable[$B9] := 20;
- XORTable[$BA] := 21;
- XORTable[$BB] := 22;
- XORTable[$BC] := 23;
- XORTable[$BD] := 24;
- XORTable[$BE] := 25;
- XORTable[$BF] := 26;
- XORTable[$CB] := 27;
- XORTable[$CD] := 28;
- XORTable[$CE] := 29;
- XORTable[$CF] := 30;
- XORTable[$D3] := 31;
- XORTable[$D6] := 32;
- XORTable[$D7] := 33;
- XORTable[$D9] := 34;
- XORTable[$DA] := 35;
- XORTable[$DB] := 36;
- XORTable[$DC] := 37;
- XORTable[$DD] := 38;
- XORTable[$DE] := 39;
- XORTable[$DF] := 40;
- XORTable[$E5] := 41;
- XORTable[$E6] := 42;
- XORTable[$E7] := 43;
- XORTable[$E9] := 44;
- XORTable[$EA] := 45;
- XORTable[$EB] := 46;
- XORTable[$EC] := 47;
- XORTable[$ED] := 48;
- XORTable[$EE] := 49;
- XORTable[$EF] := 50;
- XORTable[$F2] := 51;
- XORTable[$F3] := 52;
- XORTable[$F4] := 53;
- XORTable[$F5] := 54;
- XORTable[$F6] := 55;
- XORTable[$F7] := 56;
- XORTable[$F9] := 57;
- XORTable[$FA] := 58;
- XORTable[$FB] := 59;
- XORTable[$FC] := 60;
- XORTable[$FD] := 61;
- XORTable[$FE] := 62;
- XORTable[$FF] := 63;
- D33_DO.count := 4;
- D33_DO.t := 17;
- D33_DO.data[0].s := 0;
- D33_DO.data[0].offs := 1;
- D33_DO.data[0].v := 17;
- D33_DO.data[1].s := 0;
- D33_DO.data[1].offs := 2;
- D33_DO.data[1].v := 15;
- D33_DO.data[2].s := 2;
- D33_DO.data[2].offs := 1;
- D33_DO.data[2].v := 17;
- D33_DO.data[3].s := 2;
- D33_DO.data[3].offs := 2;
- D33_DO.data[3].v := 1;
- D33_PO.count := 4;
- D33_PO.t := 17;
- D33_PO.data[0].s := 0;
- D33_PO.data[0].offs := 1;
- D33_PO.data[0].v := 17;
- D33_PO.data[1].s := 0;
- D33_PO.data[1].offs := 2;
- D33_PO.data[1].v := 15;
- D33_PO.data[2].s := 13;
- D33_PO.data[2].offs := 1;
- D33_PO.data[2].v := 17;
- D33_PO.data[3].s := 13;
- D33_PO.data[3].offs := 2;
- D33_PO.data[3].v := 1;
- Pascal_DO.count := 5;
- Pascal_DO.t := 0;
- Pascal_DO.data[0].s := 11;
- Pascal_DO.data[0].offs := 0;
- Pascal_DO.data[0].v := 0;
- Pascal_DO.data[1].s := 11;
- Pascal_DO.data[1].offs := 1;
- Pascal_DO.data[1].v := 0;
- Pascal_DO.data[2].s := 11;
- Pascal_DO.data[2].offs := 2;
- Pascal_DO.data[2].v := 6;
- Pascal_DO.data[3].s := 11;
- Pascal_DO.data[3].offs := 14;
- Pascal_DO.data[3].v := 24;
- Pascal_DO.data[4].s := 11;
- Pascal_DO.data[4].offs := 15;
- Pascal_DO.data[4].v := 1;
- Pascal_PO.count := 5;
- Pascal_PO.t := 0;
- Pascal_PO.data[0].s := 4;
- Pascal_PO.data[0].offs := 0;
- Pascal_PO.data[0].v := 0;
- Pascal_PO.data[1].s := 4;
- Pascal_PO.data[1].offs := 1;
- Pascal_PO.data[1].v := 0;
- Pascal_PO.data[2].s := 4;
- Pascal_PO.data[2].offs := 2;
- Pascal_PO.data[2].v := 6;
- Pascal_PO.data[3].s := 4;
- Pascal_PO.data[3].offs := 14;
- Pascal_PO.data[3].v := 24;
- Pascal_PO.data[4].s := 4;
- Pascal_PO.data[4].offs := 15;
- Pascal_PO.data[4].v := 1;
- PDOS_DO.count := 8;
- PDOS_DO.t := 0;
- PDOS_DO.data[0].s := 11;
- PDOS_DO.data[0].offs := 0;
- PDOS_DO.data[0].v := 0;
- PDOS_DO.data[1].s := 11;
- PDOS_DO.data[1].offs := 2;
- PDOS_DO.data[1].v := 3;
- PDOS_DO.data[2].s := 9;
- PDOS_DO.data[2].offs := 0;
- PDOS_DO.data[2].v := 2;
- PDOS_DO.data[3].s := 9;
- PDOS_DO.data[3].offs := 2;
- PDOS_DO.data[3].v := 4;
- PDOS_DO.data[4].s := 7;
- PDOS_DO.data[4].offs := 0;
- PDOS_DO.data[4].v := 3;
- PDOS_DO.data[5].s := 7;
- PDOS_DO.data[5].offs := 2;
- PDOS_DO.data[5].v := 5;
- PDOS_DO.data[6].s := 5;
- PDOS_DO.data[6].offs := 0;
- PDOS_DO.data[6].v := 4;
- PDOS_DO.data[7].s := 5;
- PDOS_DO.data[7].offs := 2;
- PDOS_DO.data[7].v := 0;
- PDOS_PO.count := 8;
- PDOS_PO.t := 0;
- PDOS_PO.data[0].s := 4;
- PDOS_PO.data[0].offs := 0;
- PDOS_PO.data[0].v := 0;
- PDOS_PO.data[1].s := 4;
- PDOS_PO.data[1].offs := 2;
- PDOS_PO.data[1].v := 3;
- PDOS_PO.data[2].s := 6;
- PDOS_PO.data[2].offs := 0;
- PDOS_PO.data[2].v := 2;
- PDOS_PO.data[3].s := 6;
- PDOS_PO.data[3].offs := 2;
- PDOS_PO.data[3].v := 4;
- PDOS_PO.data[4].s := 8;
- PDOS_PO.data[4].offs := 0;
- PDOS_PO.data[4].v := 3;
- PDOS_PO.data[5].s := 8;
- PDOS_PO.data[5].offs := 2;
- PDOS_PO.data[5].v := 5;
- PDOS_PO.data[6].s := 10;
- PDOS_PO.data[6].offs := 0;
- PDOS_PO.data[6].v := 4;
- PDOS_PO.data[7].s := 10;
- PDOS_PO.data[7].offs := 2;
- PDOS_PO.data[7].v := 0;
- months[0] := '???';
- months[1] := 'Jan';
- months[2] := 'Feb';
- months[3] := 'Mar';
- months[4] := 'Apr';
- months[5] := 'May';
- months[6] := 'Jun';
- months[7] := 'Jul';
- months[8] := 'Aug';
- months[9] := 'Sep';
- months[10] := 'Oct';
- months[11] := 'Nov';
- months[12] := 'Dec';
- fTypes[1].value := $01;
- fTypes[1].desc := 'BAD';
- fTypes[2].value := $04;
- fTypes[2].desc := 'TXT';
- fTypes[3].value := $06;
- fTypes[3].desc := 'BIN';
- fTypes[4].value := $0F;
- fTypes[4].desc := 'DIR';
- fTypes[5].value := $19;
- fTypes[5].desc := 'ADB';
- fTypes[6].value := $1A;
- fTypes[6].desc := 'AWP';
- fTypes[7].value := $1B;
- fTypes[7].desc := 'ASP';
- fTypes[8].value := $EF;
- fTypes[8].desc := 'PAS';
- fTypes[9].value := $F0;
- fTypes[9].desc := 'CMD';
- fTypes[10].value := $FC;
- fTypes[10].desc := 'BAS';
- fTypes[11].value := $FD;
- fTypes[11].desc := 'VAR';
- fTypes[12].value := $FE;
- fTypes[12].desc := 'REL';
- fTypes[13].value := $FF;
- fTypes[13].desc := 'SYS';
- {$r+}
- dtWork.dat_Format := FORMAT_DOS;
- dtWork.dat_Flags := 0;
- dtWork.dat_StrDay := NIL;
- dtWork.dat_StrDate := ^mDate;
- dtWork.dat_StrTime := ^mTime;
- clrscr;
- writeln;
- writeln('Apple Image Utility - version 0.6');
- writeln;
- parmsOK := true;
- argC := ParamCount;
- if argC > 16
- then argC := 16;
- for i := 1 to argC
- do args[i] := ParamStr(i);
- if argC > 2
- then begin
- ch := args[3][1];
- if (ch = '''') or (ch = '"')
- then begin
- i := 2;
- newArg := '';
- repeat
- i := i + 1;
- currArg := args[i];
- newArg := newArg + currArg + ' ';
- ch := currArg[length(currArg)];
- done := (ch = '''') or (ch = '"')
- until done or (i = argC);
- if done
- then begin
- newArg := copy(newArg, 2, length(newArg) - 3);
- args[3] := newArg;
- if i = argC
- then argC := 3
- else begin
- for j := i + 1 to argC
- do args[3 + j - i] := args[j];
- argC := argC - 3
- end
- end
- end
- end;
- case argC of
- 0: begin
- write('File name? ');
- readln(ifName);
- ifTyp := classify(ifName);
- mode := cat
- end;
- 1: begin
- ifName := args[1];
- ifTyp := classify(ifName);
- mode := cat
- end;
- 2: begin
- ifName := args[1];
- ifTyp := classify(ifName);
- if (args[2] = '-r') or (args[2] = '-R')
- then begin
- if ifTyp = bitIm
- then begin
- writeln('Can''t reorder bit image!');
- parmsOK := false
- end
- else begin
- if size <> 2
- then parmsOK := false
- else begin
- ofName := ifName + '.ro';
- mode := reord
- end
- end
- end
- else if (args[2] = '-c') or (args[2] = '-C')
- then begin
- if ifTyp <> bitIm
- then begin
- writeln('Can''t convert sector image!');
- parmsOK := false
- end
- else begin
- ofName := ifName + '.si';
- mode := cvt
- end
- end
- else parmsOK := false
- end;
- 3: begin
- ifName := args[1];
- ifTyp := classify(ifName);
- option := args[2];
- size := length(option);
- if option[1] <> '-'
- then parmsOK := false
- else begin
- case option[2] of
- 'i',
- 'I': begin
- afName := args[3];
- assign(aif, afName);
- {$i-}
- reset(aif);
- {$i+}
- if IOResult <> 0
- then begin
- writeln('Can''t open ''', afName, '''!');
- parmsOK := false
- end
- else begin
- close(aif);
- afPath := afName;
- i := length(afPath);
- repeat
- ch := afPath[i];
- hit := (ch = ':') or (ch = '/') or (ch = '\');
- if not hit
- then i := i - 1
- until (i = 0) or hit;
- if hit
- then afName := copy(afPath, i + 1, length(afPath) - i);
- end;
- if size = 2
- then xlate := false
- else if size <> 3
- then parmsOK := false
- else if UpCase(option[3]) <> 'T'
- then parmsOK := false
- else xlate := true;
- mode := insert
- end;
- 'x',
- 'X': begin
- afName := args[3];
- for i := 1 to length(afName)
- do afName[i] := UpCase(afName[i]);
- if size = 2
- then xlate := false
- else if size <> 3
- then parmsOK := false
- else if UpCase(option[3]) <> 'T'
- then parmsOK := false
- else xlate := true;
- mode := extract
- end;
- 'd',
- 'D': begin
- afName := args[3];
- for i := 1 to length(afName)
- do afName[i] := UpCase(afName[i]);
- if size <> 2
- then parmsOK := false
- else mode := delete
- end;
- 'c',
- 'C': begin
- if ifTyp <> bitIm
- then begin
- writeln('Can''t convert sector image!');
- parmsOK := false
- end
- else begin
- if size <> 2
- then parmsOK := false
- else begin
- ofName := args[3];
- mode := cvt
- end
- end
- end;
- 'r',
- 'R': begin
- if ifTyp = bitIm
- then begin
- writeln('Can''t reorder bit image!');
- parmsOK := false
- end
- else begin
- if size <> 2
- then parmsOK := false
- else begin
- ofName := args[3];
- mode := reord
- end
- end
- end
- else parmsOK := false
- end
- end
- end
- else parmsOK := false
- end;
- if not parmsOK
- then begin
- writeln(' Usage:');
- writeln(' "ImU" - Directory listing of diskette image file');
- writeln(' "ImU ifN" - Directory listing of "ifN"');
- writeln(' "ImU ifN -x mfN" - Extract "mfN" from "ifN"');
- writeln(' "ImU ifN -xt mfN" - ''-x'' plus translate ''EOL''');
- writeln(' "ImU ifN -i fN" - Insert "fN" into "ifN"');
- writeln(' "ImU ifN -it fN" - ''-i'' plus translate ''EOL''');
- writeln(' "ImU ifN -d mfN" - Delete "mfN" from "ifN"');
- writeln(' "ImU ifN -r" - Reorder "ifN" creating "ifN.ro"');
- writeln(' "ImU ifN -r ofN" - Reorder "ifN" creating "ofN"');
- writeln(' "ImU ifN -c" - Convert "ifN" to "ifN.si"');
- writeln(' "ImU ifN -c ofN" - Convert "ifN" to "ofN"');
- halt(20)
- end;
- if ifTyp < bitIm
- then begin
- writeln('File missing or not image file!');
- halt(20)
- end;
- case mode of
- cat: ;
- insert: begin
- writeln('Can''t insert a file into an image yet!');
- halt(20)
- end;
- extract: begin
- writeln('Attempting to extract ''', afName,
- ''' from ''', ifName, '''');
- writeln
- end;
- delete: begin
- writeln('Can''t delete a file from an image yet!');
- halt(20)
- end;
- reord: writeln('Reordering sector image file:');
- cvt: begin
- writeln('Converting bit image file ''', ifName,
- ''' as sector image file ''', ofName, '''')
- end
- end;
- if ifTyp <> bitIm
- then begin { Load sector image file }
- f := Open(ifName, MODE_OLDFILE);
- if f = 0
- then begin
- writeln('Illogical error while opening ''', ifName, '''!');
- halt(20)
- end;
- if _Read(f, ^sectors, secImSize) <> secImSize
- then begin
- writeln('Error reading ''', ifName, '''!');
- _Close(f);
- halt(20)
- end;
- _Close(f);
- end { Load sector image file }
- else begin { Load bit image file }
- f := Open(ifName, MODE_OLDFILE);
- if f = 0
- then begin
- writeln('Couldn''t find ''', ifName, '''!');
- halt(20)
- end;
- fileSz := _Read(f, ^image, 250000);
- _Close(f);
- firstTime := true;
- lastTrk := -1;
- countA := 0;
- countD := 0;
- offset := 0;
- done := false;
- scanData := false;
- repeat
- if image[offset] = $D5
- then if image[offset + 1] = $AA
- then if image[offset + 2] = $96
- then begin
- if scanData
- then begin
- writeln;
- writeln('Address/Data field sequence error!')
- end;
- if firstTime
- then begin
- volHi := image[offset + 3];
- volLo := image[offset + 4]
- firstTime := false
- end
- else if (image[offset + 3] <> volHi)
- or (image[offset + 4] <> volLo)
- then begin
- writeln;
- writeln('Volume number mismatch!')
- end;
- trkNo := un4x4(image[offset + 5], image[offset + 6]);
- secNo := un4x4(image[offset + 7], image[offset + 8]);
- if trkNo <> lastTrk
- then begin
- lastTrk := trkNo;
- if trkNo mod 7 = 0
- then writeln;
- write(trkNo:3)
- end;
- if not ((image[offset + 11] = $DE)
- and (image[offset + 12] = $AA)
- {and (image[offset + 13] = $EB)})
- then begin
- writeln;
- writeln('Address field epilogue error!')
- end;
- offset := offset + 12;
- countA := countA + 1;
- scanData := true
- end
- else if image[offset + 2] = $AD
- then begin
- if not scanData
- then begin
- writeln;
- writeln('Address/Data field sequence error!')
- end;
- if not ((image[offset + 346] = $DE)
- and (image[offset + 347] = $AA)
- {and (image[offset + 348] = $EB)})
- then begin
- writeln;
- writeln(image[offset + 346]:4, image[offset + 347]:4,
- ' Data field epilogue error!')
- end
- else begin
- for j := 0 to 342
- do rawData[j] := image[offset + 3 + j];
- AReg := 0;
- for j := 0 to 85
- do begin
- AReg := AReg xor XORTable[rawData[j]];
- LowBits[85 - j] := AReg
- end;
- for j := 86 to 341
- do begin
- AReg := AReg xor XORTable[rawData[j]];
- workSector[j - 86] := AReg
- end;
- AReg := AReg xor XORTable[rawData[342]];
- if AReg <> 0
- then begin
- writeln(' Checksum error!')
- halt(20)
- end;
- k := 0;
- for j := 0 to 255
- do begin
- k := k - 1;
- if k < 0
- then k := 85;
- AReg := LowBits[k] and 1;
- AReg := AReg shl 1;
- LowBits[k] := LowBits[k] shr 1;
- AReg := AReg + (LowBits[k] and 1);
- LowBits[k] := LowBits[k] shr 1;
- workSector[j] := workSector[j] shl 2 + AReg
- end
- sectors[trkNo][(secNo mod 2) * 8 + secNo div 2] := workSector;
- end;
- offset := offset + 348;
- countD := countD + 1;
- scanData := false
- end
- else begin
- writeln;
- writeln('Invalid byte after ''$D5AA''!')
- end;
- offset := offset + 1
- until (offset = fileSz) or done;
- writeln;
- writeln;
- if (countA <> 560) or (countD <> 560)
- then begin
- writeln('Found ', countA, ' address fields!');
- writeln('Found ', countD, ' data fields!')
- end;
- order := oPO
- end; { Load bit image file }
- if is(PDOS_PO)
- then begin
- if is(D33_PO)
- then format := dual1
- else format := ProDOS;
- order := oPO
- end
- else if is(PDOS_DO)
- then begin
- if is(D33_DO)
- then format := dual1
- else format := ProDOS;
- order := oDO
- end
- else if is(Pascal_PO)
- then begin
- if is(D33_PO)
- then format := dual2
- else format := Pascal;
- order := oPO
- end
- else if is(Pascal_DO)
- then begin
- if is(D33_DO)
- then format := dual2
- else format := Pascal;
- order := oDO
- end
- else if is(D33_PO)
- then begin
- format := DOS33;
- order := oPO
- end
- else if is(D33_DO)
- then begin
- format := DOS33;
- order := oDO
- end
- else format := unknown;
- if order = oDO
- then for i := 0 to 34
- do begin
- rearrTrack[0] := sectors[i][0];
- rearrTrack[1] := sectors[i][14];
- rearrTrack[2] := sectors[i][13];
- rearrTrack[3] := sectors[i][12];
- rearrTrack[4] := sectors[i][11];
- rearrTrack[5] := sectors[i][10];
- rearrTrack[6] := sectors[i][9];
- rearrTrack[7] := sectors[i][8];
- rearrTrack[8] := sectors[i][7];
- rearrTrack[9] := sectors[i][6];
- rearrTrack[10] := sectors[i][5];
- rearrTrack[11] := sectors[i][4];
- rearrTrack[12] := sectors[i][3];
- rearrTrack[13] := sectors[i][2];
- rearrTrack[14] := sectors[i][1];
- rearrTrack[15] := sectors[i][15];
- sectors[i] := rearrTrack
- end;
- case mode of
- cat: begin
- if order = oPO
- then ordCh := 'P'
- else ordCh := 'D';
- if (format = dual1) or (format = dual2)
- then suffix := 'ies'
- else suffix := 'y';
- if ifTyp > bitIm
- then begin
- writeln('Displaying director', suffix, ' of ''', ifName,
- ''' (', ordCh, 'O order)');
- writeln
- end;
- if format = dual2
- then begin
- writeln('Pascal side:');
- writeln;
- format := Pascal;
- catalog;
- writeln('DOS 3.3 side:');
- writeln;
- format := DOS33;
- catalog
- end
- else if format = dual1
- then begin
- writeln('ProDOS side:');
- writeln;
- format := ProDOS;
- catalog;
- writeln('DOS 3.3 side:');
- writeln;
- format := DOS33;
- catalog
- end
- else catalog
- end;
- insert: begin
- end;
- extract: begin
- if (format = dual1) or (format = dual2)
- then begin
- write('Extract from the DOS 3.3 side? ');
- readln(ch);
- if UpCase(ch) = 'Y'
- then format := DOS33
- else if format = dual1
- then format := ProDOS
- else format := Pascal;
- writeln
- end
- else catalog;
- case format of
- unknown: ;
- DOS33: begin
- trkNo := 17;
- secNo := 15;
- repeat
- i := 0;
- repeat
- for j := 0 to 34
- do dirEnt[j] := sectors[trkNo][secNo][i * 35 + j + 11];
- if (dirEnt[0] > 0) and (dirEnt[0] <> 255)
- then begin
- dirName := '';
- for j := 0 to 29
- do dirName := dirName + UpCase(chr(dirEnt[3 + j] and $7F));
- while dirName[length(dirName)] = ' '
- do dirName := copy(dirName, 1, length(dirName) - 1);
- match := afName = dirName
- end;
- i := i + 1
- until (i = 7) or match;
- if not match
- then begin
- prevT := trkNo;
- trkNo := sectors[prevT][secNo][1];
- secNo := secD33(sectors[prevT][secNo][2])
- end
- until (trkNo = 0) or match;
- if not match
- then begin
- writeln('Can''t locate ''', afName, ''' in ''', ifName, '''');
- writeln
- end
- else begin
- {
- fileSz := (dirEnt[34] * 256 + dirEnt[33]) * 256;
- }
- scanSize := false;
- getSize := false;
- case dirEnt[2] and $7F of
- 0: begin
- fileSz := 0;
- scanSize := true
- end;
- 1,
- 2: begin
- offset := 0;
- getSize := true
- end;
- 4: begin
- offset := 2;
- getSize := true
- end;
- else { Do nothing }
- end;
- changeSize := scanSize or getSize;
- assign(aof, dirName);
- rewrite(aof);
- { get address of 1st T/S list sector }
- TSLt := dirEnt[0];
- TSLs := secD33(dirEnt[1]);
- while TSLt + TSLs <> 0
- do begin
- for i := 6 to 127
- do begin
- trkNo := sectors[TSLt][TSLs][i * 2];
- secNo := secD33(sectors[TSLt][TSLs][i * 2 + 1]);
- if trkNo + secNo <> 0
- then begin
- if scanSize
- then begin
- j := 0;
- repeat
- if sectors[trkNo][secNo][j] = 0
- then scanSize := false
- else j := j + 1
- until not scanSize or (j = 256);
- if scanSize
- then fileSz := fileSz + 256
- else fileSz := fileSz + j
- end
- else if getSize
- then begin
- fileSz := sectors[trkNo][secNo][offset + 1] * 256
- + sectors[trkNo][secNo][offset]
- + 2
- + offset;
- getSize := false
- end;
- if not xlate
- then BlockWrite(aof, sectors[trkNo][secNo], 2)
- else begin
- for j := 0 to 255
- do begin
- byt := sectors[trkNo][secNo][j] and $7F;
- if byt = $0D
- then byt := $0A;
- workSector[j] := byt
- end;
- BlockWrite(aof, workSector, 2)
- end
- end
- end
- trkNo := sectors[TSLt][TSLs][1];
- TSLs := secD33(sectors[TSLt][TSLs][2]);
- TSLt := trkNo
- end;
- close(aof);
- if changeSize
- then begin
- f := Open(dirName, MODE_OLDFILE);
- newSize := SetFileSize(f, fileSz, OFFSET_BEGINNING);
- if newSize <> fileSz
- then writeln('However unlikely, setting output file size failed!');
- _Close(f)
- end
- end
- end;
- Pascal: begin
- entries := get_dir_byte(16);
- i := 0;
- repeat
- i := i + 1;
- offset := i * 26;
- size := get_dir_byte(offset + 6);
- dirName := '';
- for j := 1 to size
- do dirName := dirName + UpCase(chr(get_dir_byte(offset + 6 + j)));
- match := afName = dirName
- until (i = entries) or match;
- if not match
- then begin
- writeln('Can''t locate ''', afName, ''' in ''', ifName, '''');
- writeln
- end
- else begin
- start := get_dir_word(offset);
- stop := get_dir_word(offset + 2);
- file_type := get_dir_word(offset + 4);
- if file_type <> 3
- then xlate := false;
- assign(aof, dirName);
- rewrite(aof);
- if not xlate
- then begin
- for i := start to stop - 1
- do begin
- trkNo := i div 8;
- secNo := (i * 2) mod 16;
- BlockWrite(aof, sectors[trkNo][secNo], 4)
- end
- end
- else begin
- if start + 2 > stop - 1
- then writeln('Size problem in text file!')
- else begin
- indent := false;
- m := 0;
- fileSz := 0;
- for i := start + 2 to stop - 1
- do begin
- trkNo := i div 8;
- secNo := (i * 2) mod 16;
- for k := 0 to 1
- do begin
- j := 0;
- repeat
- byt := sectors[trkNo][secNo + k][j];
- if indent
- then begin
- if (byt < $20) or (byt > $7F)
- then begin
- writeln('Invalid indent value!');
- writeIt := false
- end
- else if byt = $20
- then writeIt := false
- else begin
- count := byt - $20;
- byt := $20;
- writeIt := true
- end;
- indent := false
- end
- else begin
- case byt of
- 0: writeIt := false;
- $0D: begin
- byt := $0A;
- writeIt := true
- end;
- $10: begin
- indent := true;
- writeIt := false
- end
- else writeIt := true
- end;
- count := 1
- end;
- if writeIt
- then begin
- for n := 1 to count
- do begin
- workSector[m] := byt;
- m := m + 1;
- if m = 256
- then begin
- BlockWrite(aof, workSector, 2);
- m := 0
- end;
- fileSz := fileSz + 1
- end
- end
- j := j + 1
- until j = 256;
- end
- end;
- if m <> 0
- then BlockWrite(aof, workSector, 2)
- end
- end;
- close(aof);
- if xlate
- then begin { Set file size }
- f := Open(dirName, MODE_OLDFILE);
- newSize := SetFileSize(f, fileSz, OFFSET_BEGINNING);
- if newSize <> fileSz
- then writeln('However unlikely, setting output file size failed!');
- _Close(f)
- end;
- { Change date stamp }
- formatDate(get_dir_byte(offset + 25),
- get_dir_byte(offset + 24),
- mDate);
- mTime := '00:00';
- {
- writeln(mDate)
- }
- if not StrToDate(^dtWork)
- then writeln('''StrToDate'' failed!')
- else if not SetFileDate(dirName, ^dtWork.dat_Stamp)
- then writeln('Couldn''t change date stamp of ''', dirName, '''!');
- end
- end;
- ProDOS: begin
- entCount := sectors[0][4][36];
- entSz := sectors[0][4][35];
- match := false;
- blkNo := 2;
- repeat
- trkNo := blkNo div 8;
- secNo := (blkNo * 2) mod 16;
- i := 0;
- repeat
- for j := 0 to entSz - 1
- do begin
- offs := i * entSz + j + 4;
- dirEnt[j] := sectors[trkNo][secNo + offs div 256][offs mod 256]
- end;
- entTyp := dirEnt[0] shr 4;
- if (entTyp >= 1) and (entTyp <= 3)
- then begin
- dirName := '';
- size := dirEnt[0] and $0F;
- for j := 1 to size
- do dirName := dirName
- + UpCase(chr(dirEnt[j]))
- end;
- match := dirName = afName;
- i := i + 1
- until (i = entCount) or match
- if not match
- then blkNo := sectors[trkNo][secNo][3] * 256
- + sectors[trkNo][secNo][2]
- until (blkNo = 0) or match;
- if not match
- then begin
- writeln('Can''t locate ''', afName, ''' in ''', ifName, '''');
- writeln
- end
- else begin
- i := (dirEnt[0] and $F0) shr 4;
- if (i < 1) or (i > 2)
- then writeln('Can''t handle file type!')
- else begin
- { get file size }
- fileSz := dirEnt[23] * 65536 + dirEnt[22] * 256 + dirEnt[21];
- start := dirEnt[18] * 256 + dirEnt[17];
- if i = 1
- then begin
- blocks := 1;
- blkAddrs[0] := start
- end
- else begin
- i := 0;
- trkNo := start div 8;
- secNo := (start * 2) mod 16;
- repeat
- blkNo := sectors[trkNo][secNo + 1][i]
- * 256 + sectors[trkNo][secNo][i];
- blkAddrs[i] := blkNo;
- i := i + 1
- until blkNo = 0;
- blocks := i
- end;
- assign(aof, dirName);
- rewrite(aof);
- for i := 0 to blocks - 2
- do begin
- trkNo := blkAddrs[i] div 8;
- secNo := (blkAddrs[i] * 2) mod 16;
- if not xlate
- then BlockWrite(aof, sectors[trkNo][secNo], 4)
- else begin
- for k := 0 to 1
- do begin
- for j := 0 to 255
- do begin
- byt := sectors[trkNo][secNo + k][j];
- if byt = $0D
- then byt := $0A;
- workSector[j] := byt
- end;
- BlockWrite(aof, workSector, 2)
- end
- end
- end;
- close(aof);
- { Set file size }
- f := Open(dirName, MODE_OLDFILE);
- newSize := SetFileSize(f, fileSz, OFFSET_BEGINNING);
- if newSize <> fileSz
- then writeln('However unlikely, setting output file size failed!');
- _Close(f);
- { Change date stamp }
- formatDate(dirEnt[34], dirEnt[33], mDate);
- if mDate <> '<NO DATE>'
- then begin
- formatTime(dirEnt[36], dirEnt[35], mTime);
- if mTime[1] = ' '
- then mTime[1] := '0';
- if not StrToDate(^dtWork)
- then writeln('''StrToDate'' failed!')
- else if not SetFileDate(dirName, ^dtWork.dat_Stamp)
- then writeln('Couldn''t change date stamp of ''', dirName, '''!');
- end
- end
- end
- end
- end
- end;
- delete: begin
- end;
- reord: begin
- if order = oPO
- then begin
- for i := 0 to 34
- do begin
- rearrTrack[0] := sectors[i][0];
- rearrTrack[1] := sectors[i][14];
- rearrTrack[2] := sectors[i][13];
- rearrTrack[3] := sectors[i][12];
- rearrTrack[4] := sectors[i][11];
- rearrTrack[5] := sectors[i][10];
- rearrTrack[6] := sectors[i][9];
- rearrTrack[7] := sectors[i][8];
- rearrTrack[8] := sectors[i][7];
- rearrTrack[9] := sectors[i][6];
- rearrTrack[10] := sectors[i][5];
- rearrTrack[11] := sectors[i][4];
- rearrTrack[12] := sectors[i][3];
- rearrTrack[13] := sectors[i][2];
- rearrTrack[14] := sectors[i][1];
- rearrTrack[15] := sectors[i][15];
- sectors[i] := rearrTrack
- end;
- ordCh := 'P'
- end
- else ordCh := 'D';
- writeln(' Input file ''', ifName, ''' is in ''', ordCh, 'O'' order');
- writeln(' Output file is ''', ofName, '''');
- f := Open(ofName, MODE_NEWFILE);
- if _Write(f, ^sectors, secImSize) <> secImSize
- then begin
- writeln('Error writing reordered file!');
- halt(20)
- end;
- _Close(f);
- writeln
- end;
- cvt: begin
- for i := 0 to 34
- do begin
- rearrTrack[0] := sectors[i][0];
- rearrTrack[1] := sectors[i][14];
- rearrTrack[2] := sectors[i][13];
- rearrTrack[3] := sectors[i][12];
- rearrTrack[4] := sectors[i][11];
- rearrTrack[5] := sectors[i][10];
- rearrTrack[6] := sectors[i][9];
- rearrTrack[7] := sectors[i][8];
- rearrTrack[8] := sectors[i][7];
- rearrTrack[9] := sectors[i][6];
- rearrTrack[10] := sectors[i][5];
- rearrTrack[11] := sectors[i][4];
- rearrTrack[12] := sectors[i][3];
- rearrTrack[13] := sectors[i][2];
- rearrTrack[14] := sectors[i][1];
- rearrTrack[15] := sectors[i][15];
- sectors[i] := rearrTrack
- end
- f := Open(ofName, MODE_NEWFILE);
- if _Write(f, ^sectors, secImSize) <> secImSize
- then begin
- writeln('Error writing sector image file!');
- halt(20)
- end;
- _Close(f);
- writeln
- end
- end
- end.
-